package com.kfm.web.security;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.kfm.common.domain.model.LoginUser;
import com.kfm.common.exception.ServerException;
import com.kfm.common.util.JwtUtils;
import com.kfm.common.util.SecurityUtils;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Jwt 认证过滤器
 * OncePerRequestFilter 保证过滤器只会被调用一次
 */
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String jwt = extractJwtFromRequest(request);
        if (!StringUtils.hasText(jwt)) {
            filterChain.doFilter(request, response);
            return;
        }
        String subject = JwtUtils.getSubject(jwt);
        if (StringUtils.hasText(subject)) {
            LoginUser loginUser = JSON.parseObject(subject, LoginUser.class);
            // 将用户信息存入 SecurityContextHolder 中
            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(loginUser, loginUser.getPassword(), loginUser.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

            // 将 authentication 放入SecurityContextHolder中
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        filterChain.doFilter(request, response);
    }

    /**
     * 从请求中获取 JWT
     *
     * @param request 请求
     * @return JWT
     */
    private String extractJwtFromRequest(HttpServletRequest request) {
        // 从请求头中提取JWT
        return request.getHeader("Authorization");
    }
}
